home *** CD-ROM | disk | FTP | other *** search
/ Introduction to 3D Game …ogramming with DirectX 12 / Introduction-to-3D-Game-Programming-with-DirectX-12.ISO / Code.Textures / Chapter 21 Ambient Occlusion / Ssao / SsaoApp.cpp < prev   
Encoding:
C/C++ Source or Header  |  2016-03-02  |  69.2 KB  |  1,828 lines

  1. //***************************************************************************************
  2. // SsaoApp.cpp by Frank Luna (C) 2015 All Rights Reserved.
  3. //***************************************************************************************
  4.  
  5. #include "../../Common/d3dApp.h"
  6. #include "../../Common/MathHelper.h"
  7. #include "../../Common/UploadBuffer.h"
  8. #include "../../Common/GeometryGenerator.h"
  9. #include "../../Common/Camera.h"
  10. #include "FrameResource.h"
  11. #include "ShadowMap.h"
  12. #include "Ssao.h"
  13.  
  14. using Microsoft::WRL::ComPtr;
  15. using namespace DirectX;
  16. using namespace DirectX::PackedVector;
  17.  
  18. const int gNumFrameResources = 3;
  19.  
  20. // Lightweight structure stores parameters to draw a shape.  This will
  21. // vary from app-to-app.
  22. struct RenderItem
  23. {
  24.     RenderItem() = default;
  25.     RenderItem(const RenderItem& rhs) = delete;
  26.  
  27.     // World matrix of the shape that describes the object's local space
  28.     // relative to the world space, which defines the position, orientation,
  29.     // and scale of the object in the world.
  30.     XMFLOAT4X4 World = MathHelper::Identity4x4();
  31.  
  32.     XMFLOAT4X4 TexTransform = MathHelper::Identity4x4();
  33.  
  34.     // Dirty flag indicating the object data has changed and we need to update the constant buffer.
  35.     // Because we have an object cbuffer for each FrameResource, we have to apply the
  36.     // update to each FrameResource.  Thus, when we modify obect data we should set 
  37.     // NumFramesDirty = gNumFrameResources so that each frame resource gets the update.
  38.     int NumFramesDirty = gNumFrameResources;
  39.  
  40.     // Index into GPU constant buffer corresponding to the ObjectCB for this render item.
  41.     UINT ObjCBIndex = -1;
  42.  
  43.     Material* Mat = nullptr;
  44.     MeshGeometry* Geo = nullptr;
  45.  
  46.     // Primitive topology.
  47.     D3D12_PRIMITIVE_TOPOLOGY PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  48.  
  49.     // DrawIndexedInstanced parameters.
  50.     UINT IndexCount = 0;
  51.     UINT StartIndexLocation = 0;
  52.     int BaseVertexLocation = 0;
  53. };
  54.  
  55. enum class RenderLayer : int
  56. {
  57.     Opaque = 0,
  58.     Debug,
  59.     Sky,
  60.     Count
  61. };
  62.  
  63. class SsaoApp : public D3DApp
  64. {
  65. public:
  66.     SsaoApp(HINSTANCE hInstance);
  67.     SsaoApp(const SsaoApp& rhs) = delete;
  68.     SsaoApp& operator=(const SsaoApp& rhs) = delete;
  69.     ~SsaoApp();
  70.  
  71.     virtual bool Initialize()override;
  72.  
  73. private:
  74.     virtual void CreateRtvAndDsvDescriptorHeaps()override;
  75.     virtual void OnResize()override;
  76.     virtual void Update(const GameTimer& gt)override;
  77.     virtual void Draw(const GameTimer& gt)override;
  78.  
  79.     virtual void OnMouseDown(WPARAM btnState, int x, int y)override;
  80.     virtual void OnMouseUp(WPARAM btnState, int x, int y)override;
  81.     virtual void OnMouseMove(WPARAM btnState, int x, int y)override;
  82.  
  83.     void OnKeyboardInput(const GameTimer& gt);
  84.     void AnimateMaterials(const GameTimer& gt);
  85.     void UpdateObjectCBs(const GameTimer& gt);
  86.     void UpdateMaterialBuffer(const GameTimer& gt);
  87.     void UpdateShadowTransform(const GameTimer& gt);
  88.     void UpdateMainPassCB(const GameTimer& gt);
  89.     void UpdateShadowPassCB(const GameTimer& gt);
  90.     void UpdateSsaoCB(const GameTimer& gt);
  91.  
  92.     void LoadTextures();
  93.     void BuildRootSignature();
  94.     void BuildSsaoRootSignature();
  95.     void BuildDescriptorHeaps();
  96.     void BuildShadersAndInputLayout();
  97.     void BuildShapeGeometry();
  98.     void BuildSkullGeometry();
  99.     void BuildPSOs();
  100.     void BuildFrameResources();
  101.     void BuildMaterials();
  102.     void BuildRenderItems();
  103.     void DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems);
  104.     void DrawSceneToShadowMap();
  105.     void DrawNormalsAndDepth();
  106.  
  107.     CD3DX12_CPU_DESCRIPTOR_HANDLE GetCpuSrv(int index)const;
  108.     CD3DX12_GPU_DESCRIPTOR_HANDLE GetGpuSrv(int index)const;
  109.     CD3DX12_CPU_DESCRIPTOR_HANDLE GetDsv(int index)const;
  110.     CD3DX12_CPU_DESCRIPTOR_HANDLE GetRtv(int index)const;
  111.  
  112.     std::array<const CD3DX12_STATIC_SAMPLER_DESC, 7> GetStaticSamplers();
  113.  
  114. private:
  115.  
  116.     std::vector<std::unique_ptr<FrameResource>> mFrameResources;
  117.     FrameResource* mCurrFrameResource = nullptr;
  118.     int mCurrFrameResourceIndex = 0;
  119.  
  120.     ComPtr<ID3D12RootSignature> mRootSignature = nullptr;
  121.     ComPtr<ID3D12RootSignature> mSsaoRootSignature = nullptr;
  122.  
  123.     ComPtr<ID3D12DescriptorHeap> mSrvDescriptorHeap = nullptr;
  124.  
  125.     std::unordered_map<std::string, std::unique_ptr<MeshGeometry>> mGeometries;
  126.     std::unordered_map<std::string, std::unique_ptr<Material>> mMaterials;
  127.     std::unordered_map<std::string, std::unique_ptr<Texture>> mTextures;
  128.     std::unordered_map<std::string, ComPtr<ID3DBlob>> mShaders;
  129.     std::unordered_map<std::string, ComPtr<ID3D12PipelineState>> mPSOs;
  130.  
  131.     std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout;
  132.  
  133.     // List of all the render items.
  134.     std::vector<std::unique_ptr<RenderItem>> mAllRitems;
  135.  
  136.     // Render items divided by PSO.
  137.     std::vector<RenderItem*> mRitemLayer[(int)RenderLayer::Count];
  138.  
  139.     UINT mSkyTexHeapIndex = 0;
  140.     UINT mShadowMapHeapIndex = 0;
  141.     UINT mSsaoHeapIndexStart = 0;
  142.     UINT mSsaoAmbientMapIndex = 0;
  143.  
  144.     UINT mNullCubeSrvIndex = 0;
  145.     UINT mNullTexSrvIndex1 = 0;
  146.     UINT mNullTexSrvIndex2 = 0;
  147.  
  148.     CD3DX12_GPU_DESCRIPTOR_HANDLE mNullSrv;
  149.  
  150.     PassConstants mMainPassCB;  // index 0 of pass cbuffer.
  151.     PassConstants mShadowPassCB;// index 1 of pass cbuffer.
  152.  
  153.     Camera mCamera;
  154.  
  155.     std::unique_ptr<ShadowMap> mShadowMap;
  156.  
  157.     std::unique_ptr<Ssao> mSsao;
  158.  
  159.     DirectX::BoundingSphere mSceneBounds;
  160.  
  161.     float mLightNearZ = 0.0f;
  162.     float mLightFarZ = 0.0f;
  163.     XMFLOAT3 mLightPosW;
  164.     XMFLOAT4X4 mLightView = MathHelper::Identity4x4();
  165.     XMFLOAT4X4 mLightProj = MathHelper::Identity4x4();
  166.     XMFLOAT4X4 mShadowTransform = MathHelper::Identity4x4();
  167.  
  168.     float mLightRotationAngle = 0.0f;
  169.     XMFLOAT3 mBaseLightDirections[3] = {
  170.         XMFLOAT3(0.57735f, -0.57735f, 0.57735f),
  171.         XMFLOAT3(-0.57735f, -0.57735f, 0.57735f),
  172.         XMFLOAT3(0.0f, -0.707f, -0.707f)
  173.     };
  174.     XMFLOAT3 mRotatedLightDirections[3];
  175.  
  176.     POINT mLastMousePos;
  177. };
  178.  
  179. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
  180.     PSTR cmdLine, int showCmd)
  181. {
  182.     // Enable run-time memory check for debug builds.
  183. #if defined(DEBUG) | defined(_DEBUG)
  184.     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  185. #endif
  186.  
  187.     try
  188.     {
  189.         SsaoApp theApp(hInstance);
  190.         if(!theApp.Initialize())
  191.             return 0;
  192.  
  193.         return theApp.Run();
  194.     }
  195.     catch(DxException& e)
  196.     {
  197.         MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
  198.         return 0;
  199.     }
  200. }
  201.  
  202. SsaoApp::SsaoApp(HINSTANCE hInstance)
  203.     : D3DApp(hInstance)
  204. {
  205.     // Estimate the scene bounding sphere manually since we know how the scene was constructed.
  206.     // The grid is the "widest object" with a width of 20 and depth of 30.0f, and centered at
  207.     // the world space origin.  In general, you need to loop over every world space vertex
  208.     // position and compute the bounding sphere.
  209.     mSceneBounds.Center = XMFLOAT3(0.0f, 0.0f, 0.0f);
  210.     mSceneBounds.Radius = sqrtf(10.0f*10.0f + 15.0f*15.0f);
  211. }
  212.  
  213. SsaoApp::~SsaoApp()
  214. {
  215.     if(md3dDevice != nullptr)
  216.         FlushCommandQueue();
  217. }
  218.  
  219. bool SsaoApp::Initialize()
  220. {
  221.     if(!D3DApp::Initialize())
  222.         return false;
  223.  
  224.     // Reset the command list to prep for initialization commands.
  225.     ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
  226.  
  227.     mCamera.SetPosition(0.0f, 2.0f, -15.0f);
  228.  
  229.     mShadowMap = std::make_unique<ShadowMap>(md3dDevice.Get(),
  230.         2048, 2048);
  231.  
  232.     mSsao = std::make_unique<Ssao>(
  233.         md3dDevice.Get(),
  234.         mCommandList.Get(),
  235.         mClientWidth, mClientHeight);
  236.  
  237.     LoadTextures();
  238.     BuildRootSignature();
  239.     BuildSsaoRootSignature();
  240.     BuildDescriptorHeaps();
  241.     BuildShadersAndInputLayout();
  242.     BuildShapeGeometry();
  243.     BuildSkullGeometry();
  244.     BuildMaterials();
  245.     BuildRenderItems();
  246.     BuildFrameResources();
  247.     BuildPSOs();
  248.  
  249.     mSsao->SetPSOs(mPSOs["ssao"].Get(), mPSOs["ssaoBlur"].Get());
  250.  
  251.     // Execute the initialization commands.
  252.     ThrowIfFailed(mCommandList->Close());
  253.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  254.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  255.  
  256.     // Wait until initialization is complete.
  257.     FlushCommandQueue();
  258.  
  259.     return true;
  260. }
  261.  
  262. void SsaoApp::CreateRtvAndDsvDescriptorHeaps()
  263. {
  264.     // Add +1 for screen normal map, +2 for ambient maps.
  265.     D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc;
  266.     rtvHeapDesc.NumDescriptors = SwapChainBufferCount + 3;
  267.     rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
  268.     rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
  269.     rtvHeapDesc.NodeMask = 0;
  270.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
  271.         &rtvHeapDesc, IID_PPV_ARGS(mRtvHeap.GetAddressOf())));
  272.  
  273.     // Add +1 DSV for shadow map.
  274.     D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc;
  275.     dsvHeapDesc.NumDescriptors = 2;
  276.     dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
  277.     dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
  278.     dsvHeapDesc.NodeMask = 0;
  279.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
  280.         &dsvHeapDesc, IID_PPV_ARGS(mDsvHeap.GetAddressOf())));
  281. }
  282.  
  283. void SsaoApp::OnResize()
  284. {
  285.     D3DApp::OnResize();
  286.  
  287.     mCamera.SetLens(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
  288.  
  289.     if(mSsao != nullptr)
  290.     {
  291.         mSsao->OnResize(mClientWidth, mClientHeight);
  292.  
  293.         // Resources changed, so need to rebuild descriptors.
  294.         mSsao->RebuildDescriptors(mDepthStencilBuffer.Get());
  295.     }
  296. }
  297.  
  298. void SsaoApp::Update(const GameTimer& gt)
  299. {
  300.     OnKeyboardInput(gt);
  301.  
  302.     // Cycle through the circular frame resource array.
  303.     mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources;
  304.     mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();
  305.  
  306.     // Has the GPU finished processing the commands of the current frame resource?
  307.     // If not, wait until the GPU has completed commands up to this fence point.
  308.     if(mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
  309.     {
  310.         HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
  311.         ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
  312.         WaitForSingleObject(eventHandle, INFINITE);
  313.         CloseHandle(eventHandle);
  314.     }
  315.  
  316.     //
  317.     // Animate the lights (and hence shadows).
  318.     //
  319.  
  320.     mLightRotationAngle += 0.1f*gt.DeltaTime();
  321.  
  322.     XMMATRIX R = XMMatrixRotationY(mLightRotationAngle);
  323.     for(int i = 0; i < 3; ++i)
  324.     {
  325.         XMVECTOR lightDir = XMLoadFloat3(&mBaseLightDirections[i]);
  326.         lightDir = XMVector3TransformNormal(lightDir, R);
  327.         XMStoreFloat3(&mRotatedLightDirections[i], lightDir);
  328.     }
  329.  
  330.     AnimateMaterials(gt);
  331.     UpdateObjectCBs(gt);
  332.     UpdateMaterialBuffer(gt);
  333.     UpdateShadowTransform(gt);
  334.     UpdateMainPassCB(gt);
  335.     UpdateShadowPassCB(gt);
  336.     UpdateSsaoCB(gt);
  337. }
  338.  
  339. void SsaoApp::Draw(const GameTimer& gt)
  340. {
  341.     auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
  342.  
  343.     // Reuse the memory associated with command recording.
  344.     // We can only reset when the associated command lists have finished execution on the GPU.
  345.     ThrowIfFailed(cmdListAlloc->Reset());
  346.  
  347.     // A command list can be reset after it has been added to the command queue via ExecuteCommandList.
  348.     // Reusing the command list reuses memory.
  349.     ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].Get()));
  350.  
  351.     ID3D12DescriptorHeap* descriptorHeaps[] = { mSrvDescriptorHeap.Get() };
  352.     mCommandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps);
  353.  
  354.     mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
  355.  
  356.     //
  357.     // Shadow map pass.
  358.     //
  359.  
  360.     // Bind all the materials used in this scene.  For structured buffers, we can bypass the heap and 
  361.     // set as a root descriptor.
  362.     auto matBuffer = mCurrFrameResource->MaterialBuffer->Resource();
  363.     mCommandList->SetGraphicsRootShaderResourceView(2, matBuffer->GetGPUVirtualAddress());
  364.     
  365.     // Bind null SRV for shadow map pass.
  366.     mCommandList->SetGraphicsRootDescriptorTable(3, mNullSrv);     
  367.  
  368.     // Bind all the textures used in this scene.  Observe
  369.     // that we only have to specify the first descriptor in the table.  
  370.     // The root signature knows how many descriptors are expected in the table.
  371.     mCommandList->SetGraphicsRootDescriptorTable(4, mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  372.  
  373.     DrawSceneToShadowMap();
  374.  
  375.     //
  376.     // Normal/depth pass.
  377.     //
  378.     
  379.     DrawNormalsAndDepth();
  380.     
  381.     //
  382.     // Compute SSAO.
  383.     // 
  384.     
  385.     mCommandList->SetGraphicsRootSignature(mSsaoRootSignature.Get());
  386.     mSsao->ComputeSsao(mCommandList.Get(), mCurrFrameResource, 3);
  387.     
  388.     //
  389.     // Main rendering pass.
  390.     //
  391.     
  392.     mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
  393.  
  394.     // Rebind state whenever graphics root signature changes.
  395.  
  396.     // Bind all the materials used in this scene.  For structured buffers, we can bypass the heap and 
  397.     // set as a root descriptor.
  398.     matBuffer = mCurrFrameResource->MaterialBuffer->Resource();
  399.     mCommandList->SetGraphicsRootShaderResourceView(2, matBuffer->GetGPUVirtualAddress());
  400.  
  401.  
  402.     mCommandList->RSSetViewports(1, &mScreenViewport);
  403.     mCommandList->RSSetScissorRects(1, &mScissorRect);
  404.  
  405.     // Indicate a state transition on the resource usage.
  406.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  407.         D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
  408.  
  409.     // Clear the back buffer.
  410.     mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr);
  411.  
  412.     // WE ALREADY WROTE THE DEPTH INFO TO THE DEPTH BUFFER IN DrawNormalsAndDepth,
  413.     // SO DO NOT CLEAR DEPTH.
  414.  
  415.     // Specify the buffers we are going to render to.
  416.     mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
  417.  
  418.     // Bind all the textures used in this scene.  Observe
  419.     // that we only have to specify the first descriptor in the table.  
  420.     // The root signature knows how many descriptors are expected in the table.
  421.     mCommandList->SetGraphicsRootDescriptorTable(4, mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  422.     
  423.     auto passCB = mCurrFrameResource->PassCB->Resource();
  424.     mCommandList->SetGraphicsRootConstantBufferView(1, passCB->GetGPUVirtualAddress());
  425.  
  426.     // Bind the sky cube map.  For our demos, we just use one "world" cube map representing the environment
  427.     // from far away, so all objects will use the same cube map and we only need to set it once per-frame.  
  428.     // If we wanted to use "local" cube maps, we would have to change them per-object, or dynamically
  429.     // index into an array of cube maps.
  430.  
  431.     CD3DX12_GPU_DESCRIPTOR_HANDLE skyTexDescriptor(mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  432.     skyTexDescriptor.Offset(mSkyTexHeapIndex, mCbvSrvUavDescriptorSize);
  433.     mCommandList->SetGraphicsRootDescriptorTable(3, skyTexDescriptor);
  434.  
  435.     mCommandList->SetPipelineState(mPSOs["opaque"].Get());
  436.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
  437.  
  438.     mCommandList->SetPipelineState(mPSOs["debug"].Get());
  439.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Debug]);
  440.  
  441.     mCommandList->SetPipelineState(mPSOs["sky"].Get());
  442.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Sky]);
  443.  
  444.     // Indicate a state transition on the resource usage.
  445.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  446.         D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
  447.  
  448.     // Done recording commands.
  449.     ThrowIfFailed(mCommandList->Close());
  450.  
  451.     // Add the command list to the queue for execution.
  452.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  453.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  454.  
  455.     // Swap the back and front buffers
  456.     ThrowIfFailed(mSwapChain->Present(0, 0));
  457.     mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;
  458.  
  459.     // Advance the fence value to mark commands up to this fence point.
  460.     mCurrFrameResource->Fence = ++mCurrentFence;
  461.  
  462.     // Add an instruction to the command queue to set a new fence point. 
  463.     // Because we are on the GPU timeline, the new fence point won't be 
  464.     // set until the GPU finishes processing all the commands prior to this Signal().
  465.     mCommandQueue->Signal(mFence.Get(), mCurrentFence);
  466. }
  467.  
  468. void SsaoApp::OnMouseDown(WPARAM btnState, int x, int y)
  469. {
  470.     mLastMousePos.x = x;
  471.     mLastMousePos.y = y;
  472.  
  473.     SetCapture(mhMainWnd);
  474. }
  475.  
  476. void SsaoApp::OnMouseUp(WPARAM btnState, int x, int y)
  477. {
  478.     ReleaseCapture();
  479. }
  480.  
  481. void SsaoApp::OnMouseMove(WPARAM btnState, int x, int y)
  482. {
  483.     if((btnState & MK_LBUTTON) != 0)
  484.     {
  485.         // Make each pixel correspond to a quarter of a degree.
  486.         float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
  487.         float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));
  488.  
  489.         mCamera.Pitch(dy);
  490.         mCamera.RotateY(dx);
  491.     }
  492.  
  493.     mLastMousePos.x = x;
  494.     mLastMousePos.y = y;
  495. }
  496.  
  497. void SsaoApp::OnKeyboardInput(const GameTimer& gt)
  498. {
  499.     const float dt = gt.DeltaTime();
  500.  
  501.     if(GetAsyncKeyState('W') & 0x8000)
  502.         mCamera.Walk(10.0f*dt);
  503.  
  504.     if(GetAsyncKeyState('S') & 0x8000)
  505.         mCamera.Walk(-10.0f*dt);
  506.  
  507.     if(GetAsyncKeyState('A') & 0x8000)
  508.         mCamera.Strafe(-10.0f*dt);
  509.  
  510.     if(GetAsyncKeyState('D') & 0x8000)
  511.         mCamera.Strafe(10.0f*dt);
  512.  
  513.     mCamera.UpdateViewMatrix();
  514. }
  515.  
  516. void SsaoApp::AnimateMaterials(const GameTimer& gt)
  517. {
  518.     
  519. }
  520.  
  521. void SsaoApp::UpdateObjectCBs(const GameTimer& gt)
  522. {
  523.     auto currObjectCB = mCurrFrameResource->ObjectCB.get();
  524.     for(auto& e : mAllRitems)
  525.     {
  526.         // Only update the cbuffer data if the constants have changed.  
  527.         // This needs to be tracked per frame resource.
  528.         if(e->NumFramesDirty > 0)
  529.         {
  530.             XMMATRIX world = XMLoadFloat4x4(&e->World);
  531.             XMMATRIX texTransform = XMLoadFloat4x4(&e->TexTransform);
  532.  
  533.             ObjectConstants objConstants;
  534.             XMStoreFloat4x4(&objConstants.World, XMMatrixTranspose(world));
  535.             XMStoreFloat4x4(&objConstants.TexTransform, XMMatrixTranspose(texTransform));
  536.             objConstants.MaterialIndex = e->Mat->MatCBIndex;
  537.  
  538.             currObjectCB->CopyData(e->ObjCBIndex, objConstants);
  539.  
  540.             // Next FrameResource need to be updated too.
  541.             e->NumFramesDirty--;
  542.         }
  543.     }
  544. }
  545.  
  546. void SsaoApp::UpdateMaterialBuffer(const GameTimer& gt)
  547. {
  548.     auto currMaterialBuffer = mCurrFrameResource->MaterialBuffer.get();
  549.     for(auto& e : mMaterials)
  550.     {
  551.         // Only update the cbuffer data if the constants have changed.  If the cbuffer
  552.         // data changes, it needs to be updated for each FrameResource.
  553.         Material* mat = e.second.get();
  554.         if(mat->NumFramesDirty > 0)
  555.         {
  556.             XMMATRIX matTransform = XMLoadFloat4x4(&mat->MatTransform);
  557.  
  558.             MaterialData matData;
  559.             matData.DiffuseAlbedo = mat->DiffuseAlbedo;
  560.             matData.FresnelR0 = mat->FresnelR0;
  561.             matData.Roughness = mat->Roughness;
  562.             XMStoreFloat4x4(&matData.MatTransform, XMMatrixTranspose(matTransform));
  563.             matData.DiffuseMapIndex = mat->DiffuseSrvHeapIndex;
  564.             matData.NormalMapIndex = mat->NormalSrvHeapIndex;
  565.  
  566.             currMaterialBuffer->CopyData(mat->MatCBIndex, matData);
  567.  
  568.             // Next FrameResource need to be updated too.
  569.             mat->NumFramesDirty--;
  570.         }
  571.     }
  572. }
  573.  
  574. void SsaoApp::UpdateShadowTransform(const GameTimer& gt)
  575. {
  576.     // Only the first "main" light casts a shadow.
  577.     XMVECTOR lightDir = XMLoadFloat3(&mRotatedLightDirections[0]);
  578.     XMVECTOR lightPos = -2.0f*mSceneBounds.Radius*lightDir;
  579.     XMVECTOR targetPos = XMLoadFloat3(&mSceneBounds.Center);
  580.     XMVECTOR lightUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
  581.     XMMATRIX lightView = XMMatrixLookAtLH(lightPos, targetPos, lightUp);
  582.  
  583.     XMStoreFloat3(&mLightPosW, lightPos);
  584.  
  585.     // Transform bounding sphere to light space.
  586.     XMFLOAT3 sphereCenterLS;
  587.     XMStoreFloat3(&sphereCenterLS, XMVector3TransformCoord(targetPos, lightView));
  588.  
  589.     // Ortho frustum in light space encloses scene.
  590.     float l = sphereCenterLS.x - mSceneBounds.Radius;
  591.     float b = sphereCenterLS.y - mSceneBounds.Radius;
  592.     float n = sphereCenterLS.z - mSceneBounds.Radius;
  593.     float r = sphereCenterLS.x + mSceneBounds.Radius;
  594.     float t = sphereCenterLS.y + mSceneBounds.Radius;
  595.     float f = sphereCenterLS.z + mSceneBounds.Radius;
  596.  
  597.     mLightNearZ = n;
  598.     mLightFarZ = f;
  599.     XMMATRIX lightProj = XMMatrixOrthographicOffCenterLH(l, r, b, t, n, f);
  600.  
  601.     // Transform NDC space [-1,+1]^2 to texture space [0,1]^2
  602.     XMMATRIX T(
  603.         0.5f, 0.0f, 0.0f, 0.0f,
  604.         0.0f, -0.5f, 0.0f, 0.0f,
  605.         0.0f, 0.0f, 1.0f, 0.0f,
  606.         0.5f, 0.5f, 0.0f, 1.0f);
  607.  
  608.     XMMATRIX S = lightView*lightProj*T;
  609.     XMStoreFloat4x4(&mLightView, lightView);
  610.     XMStoreFloat4x4(&mLightProj, lightProj);
  611.     XMStoreFloat4x4(&mShadowTransform, S);
  612. }
  613.  
  614. void SsaoApp::UpdateMainPassCB(const GameTimer& gt)
  615. {
  616.     XMMATRIX view = mCamera.GetView();
  617.     XMMATRIX proj = mCamera.GetProj();
  618.  
  619.     XMMATRIX viewProj = XMMatrixMultiply(view, proj);
  620.     XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
  621.     XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
  622.     XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
  623.  
  624.     // Transform NDC space [-1,+1]^2 to texture space [0,1]^2
  625.     XMMATRIX T(
  626.         0.5f, 0.0f, 0.0f, 0.0f,
  627.         0.0f, -0.5f, 0.0f, 0.0f,
  628.         0.0f, 0.0f, 1.0f, 0.0f,
  629.         0.5f, 0.5f, 0.0f, 1.0f);
  630.  
  631.     XMMATRIX viewProjTex = XMMatrixMultiply(viewProj, T);
  632.     XMMATRIX shadowTransform = XMLoadFloat4x4(&mShadowTransform);
  633.  
  634.     XMStoreFloat4x4(&mMainPassCB.View, XMMatrixTranspose(view));
  635.     XMStoreFloat4x4(&mMainPassCB.InvView, XMMatrixTranspose(invView));
  636.     XMStoreFloat4x4(&mMainPassCB.Proj, XMMatrixTranspose(proj));
  637.     XMStoreFloat4x4(&mMainPassCB.InvProj, XMMatrixTranspose(invProj));
  638.     XMStoreFloat4x4(&mMainPassCB.ViewProj, XMMatrixTranspose(viewProj));
  639.     XMStoreFloat4x4(&mMainPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
  640.     XMStoreFloat4x4(&mMainPassCB.ViewProjTex, XMMatrixTranspose(viewProjTex));
  641.     XMStoreFloat4x4(&mMainPassCB.ShadowTransform, XMMatrixTranspose(shadowTransform));
  642.     mMainPassCB.EyePosW = mCamera.GetPosition3f();
  643.     mMainPassCB.RenderTargetSize = XMFLOAT2((float)mClientWidth, (float)mClientHeight);
  644.     mMainPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / mClientWidth, 1.0f / mClientHeight);
  645.     mMainPassCB.NearZ = 1.0f;
  646.     mMainPassCB.FarZ = 1000.0f;
  647.     mMainPassCB.TotalTime = gt.TotalTime();
  648.     mMainPassCB.DeltaTime = gt.DeltaTime();
  649.     mMainPassCB.AmbientLight = { 0.4f, 0.4f, 0.6f, 1.0f };
  650.     mMainPassCB.Lights[0].Direction = mRotatedLightDirections[0];
  651.     mMainPassCB.Lights[0].Strength = { 0.4f, 0.4f, 0.5f };
  652.     mMainPassCB.Lights[1].Direction = mRotatedLightDirections[1];
  653.     mMainPassCB.Lights[1].Strength = { 0.1f, 0.1f, 0.1f };
  654.     mMainPassCB.Lights[2].Direction = mRotatedLightDirections[2];
  655.     mMainPassCB.Lights[2].Strength = { 0.0f, 0.0f, 0.0f };
  656.  
  657.     auto currPassCB = mCurrFrameResource->PassCB.get();
  658.     currPassCB->CopyData(0, mMainPassCB);
  659. }
  660.  
  661. void SsaoApp::UpdateShadowPassCB(const GameTimer& gt)
  662. {
  663.     XMMATRIX view = XMLoadFloat4x4(&mLightView);
  664.     XMMATRIX proj = XMLoadFloat4x4(&mLightProj);
  665.  
  666.     XMMATRIX viewProj = XMMatrixMultiply(view, proj);
  667.     XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
  668.     XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
  669.     XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
  670.  
  671.     UINT w = mShadowMap->Width();
  672.     UINT h = mShadowMap->Height();
  673.  
  674.     XMStoreFloat4x4(&mShadowPassCB.View, XMMatrixTranspose(view));
  675.     XMStoreFloat4x4(&mShadowPassCB.InvView, XMMatrixTranspose(invView));
  676.     XMStoreFloat4x4(&mShadowPassCB.Proj, XMMatrixTranspose(proj));
  677.     XMStoreFloat4x4(&mShadowPassCB.InvProj, XMMatrixTranspose(invProj));
  678.     XMStoreFloat4x4(&mShadowPassCB.ViewProj, XMMatrixTranspose(viewProj));
  679.     XMStoreFloat4x4(&mShadowPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
  680.     mShadowPassCB.EyePosW = mLightPosW;
  681.     mShadowPassCB.RenderTargetSize = XMFLOAT2((float)w, (float)h);
  682.     mShadowPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / w, 1.0f / h);
  683.     mShadowPassCB.NearZ = mLightNearZ;
  684.     mShadowPassCB.FarZ = mLightFarZ;
  685.  
  686.     auto currPassCB = mCurrFrameResource->PassCB.get();
  687.     currPassCB->CopyData(1, mShadowPassCB);
  688. }
  689.  
  690. void SsaoApp::UpdateSsaoCB(const GameTimer& gt)
  691. {
  692.     SsaoConstants ssaoCB;
  693.  
  694.     XMMATRIX P = mCamera.GetProj();
  695.  
  696.     // Transform NDC space [-1,+1]^2 to texture space [0,1]^2
  697.     XMMATRIX T(
  698.         0.5f, 0.0f, 0.0f, 0.0f,
  699.         0.0f, -0.5f, 0.0f, 0.0f,
  700.         0.0f, 0.0f, 1.0f, 0.0f,
  701.         0.5f, 0.5f, 0.0f, 1.0f);
  702.  
  703.     ssaoCB.Proj    = mMainPassCB.Proj;
  704.     ssaoCB.InvProj = mMainPassCB.InvProj;
  705.     XMStoreFloat4x4(&ssaoCB.ProjTex, XMMatrixTranspose(P*T));
  706.  
  707.     mSsao->GetOffsetVectors(ssaoCB.OffsetVectors);
  708.  
  709.     auto blurWeights = mSsao->CalcGaussWeights(2.5f);
  710.     ssaoCB.BlurWeights[0] = XMFLOAT4(&blurWeights[0]);
  711.     ssaoCB.BlurWeights[1] = XMFLOAT4(&blurWeights[4]);
  712.     ssaoCB.BlurWeights[2] = XMFLOAT4(&blurWeights[8]);
  713.  
  714.     ssaoCB.InvRenderTargetSize = XMFLOAT2(1.0f / mSsao->SsaoMapWidth(), 1.0f / mSsao->SsaoMapHeight());
  715.  
  716.     // Coordinates given in view space.
  717.     ssaoCB.OcclusionRadius = 0.5f;
  718.     ssaoCB.OcclusionFadeStart = 0.2f;
  719.     ssaoCB.OcclusionFadeEnd = 1.0f;
  720.     ssaoCB.SurfaceEpsilon = 0.05f;
  721.  
  722.     auto currSsaoCB = mCurrFrameResource->SsaoCB.get();
  723.     currSsaoCB->CopyData(0, ssaoCB);
  724. }
  725.  
  726. void SsaoApp::LoadTextures()
  727. {
  728.     std::vector<std::string> texNames = 
  729.     {
  730.         "bricksDiffuseMap",
  731.         "bricksNormalMap",
  732.         "tileDiffuseMap",
  733.         "tileNormalMap",
  734.         "defaultDiffuseMap",
  735.         "defaultNormalMap",
  736.         "skyCubeMap"
  737.     };
  738.     
  739.     std::vector<std::wstring> texFilenames =
  740.     {
  741.         L"../../Textures/bricks2.dds",
  742.         L"../../Textures/bricks2_nmap.dds",
  743.         L"../../Textures/tile.dds",
  744.         L"../../Textures/tile_nmap.dds",
  745.         L"../../Textures/white1x1.dds",
  746.         L"../../Textures/default_nmap.dds",
  747.         L"../../Textures/sunsetcube1024.dds"
  748.     };
  749.     
  750.     for(int i = 0; i < (int)texNames.size(); ++i)
  751.     {
  752.         auto texMap = std::make_unique<Texture>();
  753.         texMap->Name = texNames[i];
  754.         texMap->Filename = texFilenames[i];
  755.         ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  756.             mCommandList.Get(), texMap->Filename.c_str(),
  757.             texMap->Resource, texMap->UploadHeap));
  758.             
  759.         mTextures[texMap->Name] = std::move(texMap);
  760.     }        
  761. }
  762.  
  763. void SsaoApp::BuildRootSignature()
  764. {
  765.     CD3DX12_DESCRIPTOR_RANGE texTable0;
  766.     texTable0.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 3, 0, 0);
  767.  
  768.     CD3DX12_DESCRIPTOR_RANGE texTable1;
  769.     texTable1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 10, 3, 0);
  770.  
  771.     // Root parameter can be a table, root descriptor or root constants.
  772.     CD3DX12_ROOT_PARAMETER slotRootParameter[5];
  773.  
  774.     // Perfomance TIP: Order from most frequent to least frequent.
  775.     slotRootParameter[0].InitAsConstantBufferView(0);
  776.     slotRootParameter[1].InitAsConstantBufferView(1);
  777.     slotRootParameter[2].InitAsShaderResourceView(0, 1);
  778.     slotRootParameter[3].InitAsDescriptorTable(1, &texTable0, D3D12_SHADER_VISIBILITY_PIXEL);
  779.     slotRootParameter[4].InitAsDescriptorTable(1, &texTable1, D3D12_SHADER_VISIBILITY_PIXEL);
  780.  
  781.  
  782.     auto staticSamplers = GetStaticSamplers();
  783.  
  784.     // A root signature is an array of root parameters.
  785.     CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(5, slotRootParameter,
  786.         (UINT)staticSamplers.size(), staticSamplers.data(),
  787.         D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
  788.  
  789.     // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
  790.     ComPtr<ID3DBlob> serializedRootSig = nullptr;
  791.     ComPtr<ID3DBlob> errorBlob = nullptr;
  792.     HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
  793.         serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
  794.  
  795.     if(errorBlob != nullptr)
  796.     {
  797.         ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
  798.     }
  799.     ThrowIfFailed(hr);
  800.  
  801.     ThrowIfFailed(md3dDevice->CreateRootSignature(
  802.         0,
  803.         serializedRootSig->GetBufferPointer(),
  804.         serializedRootSig->GetBufferSize(),
  805.         IID_PPV_ARGS(mRootSignature.GetAddressOf())));
  806. }
  807.  
  808. void SsaoApp::BuildSsaoRootSignature()
  809. {
  810.     CD3DX12_DESCRIPTOR_RANGE texTable0;
  811.     texTable0.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 2, 0, 0);
  812.  
  813.     CD3DX12_DESCRIPTOR_RANGE texTable1;
  814.     texTable1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 2, 0);
  815.  
  816.     // Root parameter can be a table, root descriptor or root constants.
  817.     CD3DX12_ROOT_PARAMETER slotRootParameter[4];
  818.  
  819.     // Perfomance TIP: Order from most frequent to least frequent.
  820.     slotRootParameter[0].InitAsConstantBufferView(0);
  821.     slotRootParameter[1].InitAsConstants(1, 1);
  822.     slotRootParameter[2].InitAsDescriptorTable(1, &texTable0, D3D12_SHADER_VISIBILITY_PIXEL);
  823.     slotRootParameter[3].InitAsDescriptorTable(1, &texTable1, D3D12_SHADER_VISIBILITY_PIXEL);
  824.  
  825.     const CD3DX12_STATIC_SAMPLER_DESC pointClamp(
  826.         0, // shaderRegister
  827.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  828.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  829.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  830.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  831.  
  832.     const CD3DX12_STATIC_SAMPLER_DESC linearClamp(
  833.         1, // shaderRegister
  834.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  835.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  836.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  837.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  838.  
  839.     const CD3DX12_STATIC_SAMPLER_DESC depthMapSam(
  840.         2, // shaderRegister
  841.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  842.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressU
  843.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressV
  844.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressW
  845.         0.0f,
  846.         0,
  847.         D3D12_COMPARISON_FUNC_LESS_EQUAL,
  848.         D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE); 
  849.  
  850.     const CD3DX12_STATIC_SAMPLER_DESC linearWrap(
  851.         3, // shaderRegister
  852.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  853.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  854.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  855.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  856.  
  857.     std::array<CD3DX12_STATIC_SAMPLER_DESC, 4> staticSamplers =
  858.     {
  859.         pointClamp, linearClamp, depthMapSam, linearWrap
  860.     };
  861.  
  862.     // A root signature is an array of root parameters.
  863.     CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(4, slotRootParameter,
  864.         (UINT)staticSamplers.size(), staticSamplers.data(),
  865.         D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
  866.  
  867.     // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
  868.     ComPtr<ID3DBlob> serializedRootSig = nullptr;
  869.     ComPtr<ID3DBlob> errorBlob = nullptr;
  870.     HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
  871.         serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
  872.  
  873.     if(errorBlob != nullptr)
  874.     {
  875.         ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
  876.     }
  877.     ThrowIfFailed(hr);
  878.  
  879.     ThrowIfFailed(md3dDevice->CreateRootSignature(
  880.         0,
  881.         serializedRootSig->GetBufferPointer(),
  882.         serializedRootSig->GetBufferSize(),
  883.         IID_PPV_ARGS(mSsaoRootSignature.GetAddressOf())));
  884. }
  885.  
  886. void SsaoApp::BuildDescriptorHeaps()
  887. {
  888.     //
  889.     // Create the SRV heap.
  890.     //
  891.     D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
  892.     srvHeapDesc.NumDescriptors = 18;
  893.     srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
  894.     srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
  895.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&mSrvDescriptorHeap)));
  896.  
  897.     //
  898.     // Fill out the heap with actual descriptors.
  899.     //
  900.     CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
  901.  
  902.     std::vector<ComPtr<ID3D12Resource>> tex2DList = 
  903.     {
  904.         mTextures["bricksDiffuseMap"]->Resource,
  905.         mTextures["bricksNormalMap"]->Resource,
  906.         mTextures["tileDiffuseMap"]->Resource,
  907.         mTextures["tileNormalMap"]->Resource,
  908.         mTextures["defaultDiffuseMap"]->Resource,
  909.         mTextures["defaultNormalMap"]->Resource
  910.     };
  911.     
  912.     auto skyCubeMap = mTextures["skyCubeMap"]->Resource;
  913.  
  914.     D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  915.     srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  916.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  917.     srvDesc.Texture2D.MostDetailedMip = 0;
  918.     srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
  919.     
  920.     for(UINT i = 0; i < (UINT)tex2DList.size(); ++i)
  921.     {
  922.         srvDesc.Format = tex2DList[i]->GetDesc().Format;
  923.         srvDesc.Texture2D.MipLevels = tex2DList[i]->GetDesc().MipLevels;
  924.         md3dDevice->CreateShaderResourceView(tex2DList[i].Get(), &srvDesc, hDescriptor);
  925.  
  926.         // next descriptor
  927.         hDescriptor.Offset(1, mCbvSrvUavDescriptorSize);
  928.     }
  929.     
  930.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
  931.     srvDesc.TextureCube.MostDetailedMip = 0;
  932.     srvDesc.TextureCube.MipLevels = skyCubeMap->GetDesc().MipLevels;
  933.     srvDesc.TextureCube.ResourceMinLODClamp = 0.0f;
  934.     srvDesc.Format = skyCubeMap->GetDesc().Format;
  935.     md3dDevice->CreateShaderResourceView(skyCubeMap.Get(), &srvDesc, hDescriptor);
  936.     
  937.     mSkyTexHeapIndex = (UINT)tex2DList.size();
  938.     mShadowMapHeapIndex = mSkyTexHeapIndex + 1;
  939.     mSsaoHeapIndexStart = mShadowMapHeapIndex + 1;
  940.     mSsaoAmbientMapIndex = mSsaoHeapIndexStart + 3;
  941.     mNullCubeSrvIndex = mSsaoHeapIndexStart + 5;
  942.     mNullTexSrvIndex1 = mNullCubeSrvIndex + 1;
  943.     mNullTexSrvIndex2 = mNullTexSrvIndex1 + 1;
  944.  
  945.     auto nullSrv = GetCpuSrv(mNullCubeSrvIndex);
  946.     mNullSrv = GetGpuSrv(mNullCubeSrvIndex);
  947.  
  948.     md3dDevice->CreateShaderResourceView(nullptr, &srvDesc, nullSrv);
  949.     nullSrv.Offset(1, mCbvSrvUavDescriptorSize);
  950.  
  951.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  952.     srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  953.     srvDesc.Texture2D.MostDetailedMip = 0;
  954.     srvDesc.Texture2D.MipLevels = 1;
  955.     srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
  956.     md3dDevice->CreateShaderResourceView(nullptr, &srvDesc, nullSrv);
  957.  
  958.     nullSrv.Offset(1, mCbvSrvUavDescriptorSize);
  959.     md3dDevice->CreateShaderResourceView(nullptr, &srvDesc, nullSrv);
  960.  
  961.     mShadowMap->BuildDescriptors(
  962.         GetCpuSrv(mShadowMapHeapIndex),
  963.         GetGpuSrv(mShadowMapHeapIndex),
  964.         GetDsv(1));
  965.  
  966.     mSsao->BuildDescriptors(
  967.         mDepthStencilBuffer.Get(),
  968.         GetCpuSrv(mSsaoHeapIndexStart),
  969.         GetGpuSrv(mSsaoHeapIndexStart),
  970.         GetRtv(SwapChainBufferCount),
  971.         mCbvSrvUavDescriptorSize,
  972.         mRtvDescriptorSize);
  973. }
  974.  
  975. void SsaoApp::BuildShadersAndInputLayout()
  976. {
  977.     const D3D_SHADER_MACRO alphaTestDefines[] =
  978.     {
  979.         "ALPHA_TEST", "1",
  980.         NULL, NULL
  981.     };
  982.  
  983.     mShaders["standardVS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "VS", "vs_5_1");
  984.     mShaders["opaquePS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "PS", "ps_5_1");
  985.  
  986.     mShaders["shadowVS"] = d3dUtil::CompileShader(L"Shaders\\Shadows.hlsl", nullptr, "VS", "vs_5_1");
  987.     mShaders["shadowOpaquePS"] = d3dUtil::CompileShader(L"Shaders\\Shadows.hlsl", nullptr, "PS", "ps_5_1");
  988.     mShaders["shadowAlphaTestedPS"] = d3dUtil::CompileShader(L"Shaders\\Shadows.hlsl", alphaTestDefines, "PS", "ps_5_1");
  989.     
  990.     mShaders["debugVS"] = d3dUtil::CompileShader(L"Shaders\\ShadowDebug.hlsl", nullptr, "VS", "vs_5_1");
  991.     mShaders["debugPS"] = d3dUtil::CompileShader(L"Shaders\\ShadowDebug.hlsl", nullptr, "PS", "ps_5_1");
  992.  
  993.     mShaders["drawNormalsVS"] = d3dUtil::CompileShader(L"Shaders\\DrawNormals.hlsl", nullptr, "VS", "vs_5_1");
  994.     mShaders["drawNormalsPS"] = d3dUtil::CompileShader(L"Shaders\\DrawNormals.hlsl", nullptr, "PS", "ps_5_1");
  995.  
  996.     mShaders["ssaoVS"] = d3dUtil::CompileShader(L"Shaders\\Ssao.hlsl", nullptr, "VS", "vs_5_1");
  997.     mShaders["ssaoPS"] = d3dUtil::CompileShader(L"Shaders\\Ssao.hlsl", nullptr, "PS", "ps_5_1");
  998.  
  999.     mShaders["ssaoBlurVS"] = d3dUtil::CompileShader(L"Shaders\\SsaoBlur.hlsl", nullptr, "VS", "vs_5_1");
  1000.     mShaders["ssaoBlurPS"] = d3dUtil::CompileShader(L"Shaders\\SsaoBlur.hlsl", nullptr, "PS", "ps_5_1");
  1001.  
  1002.     mShaders["skyVS"] = d3dUtil::CompileShader(L"Shaders\\Sky.hlsl", nullptr, "VS", "vs_5_1");
  1003.     mShaders["skyPS"] = d3dUtil::CompileShader(L"Shaders\\Sky.hlsl", nullptr, "PS", "ps_5_1");
  1004.  
  1005.     mInputLayout =
  1006.     {
  1007.         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  1008.         { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  1009.         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  1010.         { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 32, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  1011.     };
  1012. }
  1013.  
  1014. void SsaoApp::BuildShapeGeometry()
  1015. {
  1016.     GeometryGenerator geoGen;
  1017.     GeometryGenerator::MeshData box = geoGen.CreateBox(1.0f, 1.0f, 1.0f, 3);
  1018.     GeometryGenerator::MeshData grid = geoGen.CreateGrid(20.0f, 30.0f, 60, 40);
  1019.     GeometryGenerator::MeshData sphere = geoGen.CreateSphere(0.5f, 20, 20);
  1020.     GeometryGenerator::MeshData cylinder = geoGen.CreateCylinder(0.5f, 0.3f, 3.0f, 20, 20);
  1021.     GeometryGenerator::MeshData quad = geoGen.CreateQuad(0.0f, 0.0f, 1.0f, 1.0f, 0.0f);
  1022.     
  1023.     //
  1024.     // We are concatenating all the geometry into one big vertex/index buffer.  So
  1025.     // define the regions in the buffer each submesh covers.
  1026.     //
  1027.  
  1028.     // Cache the vertex offsets to each object in the concatenated vertex buffer.
  1029.     UINT boxVertexOffset = 0;
  1030.     UINT gridVertexOffset = (UINT)box.Vertices.size();
  1031.     UINT sphereVertexOffset = gridVertexOffset + (UINT)grid.Vertices.size();
  1032.     UINT cylinderVertexOffset = sphereVertexOffset + (UINT)sphere.Vertices.size();
  1033.     UINT quadVertexOffset = cylinderVertexOffset + (UINT)cylinder.Vertices.size();
  1034.  
  1035.     // Cache the starting index for each object in the concatenated index buffer.
  1036.     UINT boxIndexOffset = 0;
  1037.     UINT gridIndexOffset = (UINT)box.Indices32.size();
  1038.     UINT sphereIndexOffset = gridIndexOffset + (UINT)grid.Indices32.size();
  1039.     UINT cylinderIndexOffset = sphereIndexOffset + (UINT)sphere.Indices32.size();
  1040.     UINT quadIndexOffset = cylinderIndexOffset + (UINT)cylinder.Indices32.size();
  1041.  
  1042.     SubmeshGeometry boxSubmesh;
  1043.     boxSubmesh.IndexCount = (UINT)box.Indices32.size();
  1044.     boxSubmesh.StartIndexLocation = boxIndexOffset;
  1045.     boxSubmesh.BaseVertexLocation = boxVertexOffset;
  1046.  
  1047.     SubmeshGeometry gridSubmesh;
  1048.     gridSubmesh.IndexCount = (UINT)grid.Indices32.size();
  1049.     gridSubmesh.StartIndexLocation = gridIndexOffset;
  1050.     gridSubmesh.BaseVertexLocation = gridVertexOffset;
  1051.  
  1052.     SubmeshGeometry sphereSubmesh;
  1053.     sphereSubmesh.IndexCount = (UINT)sphere.Indices32.size();
  1054.     sphereSubmesh.StartIndexLocation = sphereIndexOffset;
  1055.     sphereSubmesh.BaseVertexLocation = sphereVertexOffset;
  1056.  
  1057.     SubmeshGeometry cylinderSubmesh;
  1058.     cylinderSubmesh.IndexCount = (UINT)cylinder.Indices32.size();
  1059.     cylinderSubmesh.StartIndexLocation = cylinderIndexOffset;
  1060.     cylinderSubmesh.BaseVertexLocation = cylinderVertexOffset;
  1061.  
  1062.     SubmeshGeometry quadSubmesh;
  1063.     quadSubmesh.IndexCount = (UINT)quad.Indices32.size();
  1064.     quadSubmesh.StartIndexLocation = quadIndexOffset;
  1065.     quadSubmesh.BaseVertexLocation = quadVertexOffset;
  1066.  
  1067.     //
  1068.     // Extract the vertex elements we are interested in and pack the
  1069.     // vertices of all the meshes into one vertex buffer.
  1070.     //
  1071.  
  1072.     auto totalVertexCount =
  1073.         box.Vertices.size() +
  1074.         grid.Vertices.size() +
  1075.         sphere.Vertices.size() +
  1076.         cylinder.Vertices.size() + 
  1077.         quad.Vertices.size();
  1078.  
  1079.     std::vector<Vertex> vertices(totalVertexCount);
  1080.  
  1081.     UINT k = 0;
  1082.     for(size_t i = 0; i < box.Vertices.size(); ++i, ++k)
  1083.     {
  1084.         vertices[k].Pos = box.Vertices[i].Position;
  1085.         vertices[k].Normal = box.Vertices[i].Normal;
  1086.         vertices[k].TexC = box.Vertices[i].TexC;
  1087.         vertices[k].TangentU = box.Vertices[i].TangentU;
  1088.     }
  1089.  
  1090.     for(size_t i = 0; i < grid.Vertices.size(); ++i, ++k)
  1091.     {
  1092.         vertices[k].Pos = grid.Vertices[i].Position;
  1093.         vertices[k].Normal = grid.Vertices[i].Normal;
  1094.         vertices[k].TexC = grid.Vertices[i].TexC;
  1095.         vertices[k].TangentU = grid.Vertices[i].TangentU;
  1096.     }
  1097.  
  1098.     for(size_t i = 0; i < sphere.Vertices.size(); ++i, ++k)
  1099.     {
  1100.         vertices[k].Pos = sphere.Vertices[i].Position;
  1101.         vertices[k].Normal = sphere.Vertices[i].Normal;
  1102.         vertices[k].TexC = sphere.Vertices[i].TexC;
  1103.         vertices[k].TangentU = sphere.Vertices[i].TangentU;
  1104.     }
  1105.  
  1106.     for(size_t i = 0; i < cylinder.Vertices.size(); ++i, ++k)
  1107.     {
  1108.         vertices[k].Pos = cylinder.Vertices[i].Position;
  1109.         vertices[k].Normal = cylinder.Vertices[i].Normal;
  1110.         vertices[k].TexC = cylinder.Vertices[i].TexC;
  1111.         vertices[k].TangentU = cylinder.Vertices[i].TangentU;
  1112.     }
  1113.  
  1114.     for(int i = 0; i < quad.Vertices.size(); ++i, ++k)
  1115.     {
  1116.         vertices[k].Pos = quad.Vertices[i].Position;
  1117.         vertices[k].Normal = quad.Vertices[i].Normal;
  1118.         vertices[k].TexC = quad.Vertices[i].TexC;
  1119.         vertices[k].TangentU = quad.Vertices[i].TangentU;
  1120.     }
  1121.  
  1122.     std::vector<std::uint16_t> indices;
  1123.     indices.insert(indices.end(), std::begin(box.GetIndices16()), std::end(box.GetIndices16()));
  1124.     indices.insert(indices.end(), std::begin(grid.GetIndices16()), std::end(grid.GetIndices16()));
  1125.     indices.insert(indices.end(), std::begin(sphere.GetIndices16()), std::end(sphere.GetIndices16()));
  1126.     indices.insert(indices.end(), std::begin(cylinder.GetIndices16()), std::end(cylinder.GetIndices16()));
  1127.     indices.insert(indices.end(), std::begin(quad.GetIndices16()), std::end(quad.GetIndices16()));
  1128.  
  1129.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  1130.     const UINT ibByteSize = (UINT)indices.size()  * sizeof(std::uint16_t);
  1131.  
  1132.     auto geo = std::make_unique<MeshGeometry>();
  1133.     geo->Name = "shapeGeo";
  1134.  
  1135.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  1136.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  1137.  
  1138.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  1139.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  1140.  
  1141.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  1142.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  1143.  
  1144.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  1145.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  1146.  
  1147.     geo->VertexByteStride = sizeof(Vertex);
  1148.     geo->VertexBufferByteSize = vbByteSize;
  1149.     geo->IndexFormat = DXGI_FORMAT_R16_UINT;
  1150.     geo->IndexBufferByteSize = ibByteSize;
  1151.  
  1152.     geo->DrawArgs["box"] = boxSubmesh;
  1153.     geo->DrawArgs["grid"] = gridSubmesh;
  1154.     geo->DrawArgs["sphere"] = sphereSubmesh;
  1155.     geo->DrawArgs["cylinder"] = cylinderSubmesh;
  1156.     geo->DrawArgs["quad"] = quadSubmesh;
  1157.  
  1158.     mGeometries[geo->Name] = std::move(geo);
  1159. }
  1160.  
  1161. void SsaoApp::BuildSkullGeometry()
  1162. {
  1163.     std::ifstream fin("Models/skull.txt");
  1164.  
  1165.     if (!fin)
  1166.     {
  1167.         MessageBox(0, L"Models/skull.txt not found.", 0, 0);
  1168.         return;
  1169.     }
  1170.  
  1171.     UINT vcount = 0;
  1172.     UINT tcount = 0;
  1173.     std::string ignore;
  1174.  
  1175.     fin >> ignore >> vcount;
  1176.     fin >> ignore >> tcount;
  1177.     fin >> ignore >> ignore >> ignore >> ignore;
  1178.  
  1179.     XMFLOAT3 vMinf3(+MathHelper::Infinity, +MathHelper::Infinity, +MathHelper::Infinity);
  1180.     XMFLOAT3 vMaxf3(-MathHelper::Infinity, -MathHelper::Infinity, -MathHelper::Infinity);
  1181.  
  1182.     XMVECTOR vMin = XMLoadFloat3(&vMinf3);
  1183.     XMVECTOR vMax = XMLoadFloat3(&vMaxf3);
  1184.  
  1185.     std::vector<Vertex> vertices(vcount);
  1186.     for (UINT i = 0; i < vcount; ++i)
  1187.     {
  1188.         fin >> vertices[i].Pos.x >> vertices[i].Pos.y >> vertices[i].Pos.z;
  1189.         fin >> vertices[i].Normal.x >> vertices[i].Normal.y >> vertices[i].Normal.z;
  1190.  
  1191.         vertices[i].TexC = { 0.0f, 0.0f };
  1192.  
  1193.         XMVECTOR P = XMLoadFloat3(&vertices[i].Pos);
  1194.  
  1195.         XMVECTOR N = XMLoadFloat3(&vertices[i].Normal);
  1196.  
  1197.         // Generate a tangent vector so normal mapping works.  We aren't applying
  1198.         // a texture map to the skull, so we just need any tangent vector so that
  1199.         // the math works out to give us the original interpolated vertex normal.
  1200.         XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
  1201.         if (fabsf(XMVectorGetX(XMVector3Dot(N, up))) < 1.0f - 0.001f)
  1202.         {
  1203.             XMVECTOR T = XMVector3Normalize(XMVector3Cross(up, N));
  1204.             XMStoreFloat3(&vertices[i].TangentU, T);
  1205.         }
  1206.         else
  1207.         {
  1208.             up = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f);
  1209.             XMVECTOR T = XMVector3Normalize(XMVector3Cross(N, up));
  1210.             XMStoreFloat3(&vertices[i].TangentU, T);
  1211.         }
  1212.  
  1213.  
  1214.         vMin = XMVectorMin(vMin, P);
  1215.         vMax = XMVectorMax(vMax, P);
  1216.     }
  1217.  
  1218.     BoundingBox bounds;
  1219.     XMStoreFloat3(&bounds.Center, 0.5f*(vMin + vMax));
  1220.     XMStoreFloat3(&bounds.Extents, 0.5f*(vMax - vMin));
  1221.  
  1222.     fin >> ignore;
  1223.     fin >> ignore;
  1224.     fin >> ignore;
  1225.  
  1226.     std::vector<std::int32_t> indices(3 * tcount);
  1227.     for (UINT i = 0; i < tcount; ++i)
  1228.     {
  1229.         fin >> indices[i * 3 + 0] >> indices[i * 3 + 1] >> indices[i * 3 + 2];
  1230.     }
  1231.  
  1232.     fin.close();
  1233.  
  1234.     //
  1235.     // Pack the indices of all the meshes into one index buffer.
  1236.     //
  1237.  
  1238.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  1239.  
  1240.     const UINT ibByteSize = (UINT)indices.size() * sizeof(std::int32_t);
  1241.  
  1242.     auto geo = std::make_unique<MeshGeometry>();
  1243.     geo->Name = "skullGeo";
  1244.  
  1245.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  1246.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  1247.  
  1248.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  1249.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  1250.  
  1251.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  1252.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  1253.  
  1254.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  1255.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  1256.  
  1257.     geo->VertexByteStride = sizeof(Vertex);
  1258.     geo->VertexBufferByteSize = vbByteSize;
  1259.     geo->IndexFormat = DXGI_FORMAT_R32_UINT;
  1260.     geo->IndexBufferByteSize = ibByteSize;
  1261.  
  1262.     SubmeshGeometry submesh;
  1263.     submesh.IndexCount = (UINT)indices.size();
  1264.     submesh.StartIndexLocation = 0;
  1265.     submesh.BaseVertexLocation = 0;
  1266.     submesh.Bounds = bounds;
  1267.  
  1268.     geo->DrawArgs["skull"] = submesh;
  1269.  
  1270.     mGeometries[geo->Name] = std::move(geo);
  1271. }
  1272.  
  1273. void SsaoApp::BuildPSOs()
  1274. {
  1275.     D3D12_GRAPHICS_PIPELINE_STATE_DESC basePsoDesc;
  1276.  
  1277.     
  1278.     ZeroMemory(&basePsoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
  1279.     basePsoDesc.InputLayout = { mInputLayout.data(), (UINT)mInputLayout.size() };
  1280.     basePsoDesc.pRootSignature = mRootSignature.Get();
  1281.     basePsoDesc.VS =
  1282.     { 
  1283.         reinterpret_cast<BYTE*>(mShaders["standardVS"]->GetBufferPointer()), 
  1284.         mShaders["standardVS"]->GetBufferSize()
  1285.     };
  1286.     basePsoDesc.PS =
  1287.     { 
  1288.         reinterpret_cast<BYTE*>(mShaders["opaquePS"]->GetBufferPointer()),
  1289.         mShaders["opaquePS"]->GetBufferSize()
  1290.     };
  1291.     basePsoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
  1292.     basePsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
  1293.     basePsoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
  1294.     basePsoDesc.SampleMask = UINT_MAX;
  1295.     basePsoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
  1296.     basePsoDesc.NumRenderTargets = 1;
  1297.     basePsoDesc.RTVFormats[0] = mBackBufferFormat;
  1298.     basePsoDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;
  1299.     basePsoDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
  1300.     basePsoDesc.DSVFormat = mDepthStencilFormat;
  1301.  
  1302.     //
  1303.     // PSO for opaque objects.
  1304.     //
  1305.  
  1306.     D3D12_GRAPHICS_PIPELINE_STATE_DESC opaquePsoDesc = basePsoDesc;
  1307.     opaquePsoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_EQUAL;
  1308.     opaquePsoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
  1309.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&opaquePsoDesc, IID_PPV_ARGS(&mPSOs["opaque"])));
  1310.  
  1311.     //
  1312.     // PSO for shadow map pass.
  1313.     //
  1314.     D3D12_GRAPHICS_PIPELINE_STATE_DESC smapPsoDesc = basePsoDesc;
  1315.     smapPsoDesc.RasterizerState.DepthBias = 100000;
  1316.     smapPsoDesc.RasterizerState.DepthBiasClamp = 0.0f;
  1317.     smapPsoDesc.RasterizerState.SlopeScaledDepthBias = 1.0f;
  1318.     smapPsoDesc.pRootSignature = mRootSignature.Get();
  1319.     smapPsoDesc.VS =
  1320.     {
  1321.         reinterpret_cast<BYTE*>(mShaders["shadowVS"]->GetBufferPointer()),
  1322.         mShaders["shadowVS"]->GetBufferSize()
  1323.     };
  1324.     smapPsoDesc.PS =
  1325.     {
  1326.         reinterpret_cast<BYTE*>(mShaders["shadowOpaquePS"]->GetBufferPointer()),
  1327.         mShaders["shadowOpaquePS"]->GetBufferSize()
  1328.     };
  1329.     
  1330.     // Shadow map pass does not have a render target.
  1331.     smapPsoDesc.RTVFormats[0] = DXGI_FORMAT_UNKNOWN;
  1332.     smapPsoDesc.NumRenderTargets = 0;
  1333.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&smapPsoDesc, IID_PPV_ARGS(&mPSOs["shadow_opaque"])));
  1334.  
  1335.     //
  1336.     // PSO for debug layer.
  1337.     //
  1338.     D3D12_GRAPHICS_PIPELINE_STATE_DESC debugPsoDesc = basePsoDesc;
  1339.     debugPsoDesc.pRootSignature = mRootSignature.Get();
  1340.     debugPsoDesc.VS =
  1341.     {
  1342.         reinterpret_cast<BYTE*>(mShaders["debugVS"]->GetBufferPointer()),
  1343.         mShaders["debugVS"]->GetBufferSize()
  1344.     };
  1345.     debugPsoDesc.PS =
  1346.     {
  1347.         reinterpret_cast<BYTE*>(mShaders["debugPS"]->GetBufferPointer()),
  1348.         mShaders["debugPS"]->GetBufferSize()
  1349.     };
  1350.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&debugPsoDesc, IID_PPV_ARGS(&mPSOs["debug"])));
  1351.  
  1352.     //
  1353.     // PSO for drawing normals.
  1354.     //
  1355.     D3D12_GRAPHICS_PIPELINE_STATE_DESC drawNormalsPsoDesc = basePsoDesc;
  1356.     drawNormalsPsoDesc.VS =
  1357.     {
  1358.         reinterpret_cast<BYTE*>(mShaders["drawNormalsVS"]->GetBufferPointer()),
  1359.         mShaders["drawNormalsVS"]->GetBufferSize()
  1360.     };
  1361.     drawNormalsPsoDesc.PS =
  1362.     {
  1363.         reinterpret_cast<BYTE*>(mShaders["drawNormalsPS"]->GetBufferPointer()),
  1364.         mShaders["drawNormalsPS"]->GetBufferSize()
  1365.     };
  1366.     drawNormalsPsoDesc.RTVFormats[0] = Ssao::NormalMapFormat;
  1367.     drawNormalsPsoDesc.SampleDesc.Count = 1;
  1368.     drawNormalsPsoDesc.SampleDesc.Quality = 0;
  1369.     drawNormalsPsoDesc.DSVFormat = mDepthStencilFormat;
  1370.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&drawNormalsPsoDesc, IID_PPV_ARGS(&mPSOs["drawNormals"])));
  1371.  
  1372.     //
  1373.     // PSO for SSAO.
  1374.     //
  1375.     D3D12_GRAPHICS_PIPELINE_STATE_DESC ssaoPsoDesc = basePsoDesc;
  1376.     ssaoPsoDesc.InputLayout = { nullptr, 0 };
  1377.     ssaoPsoDesc.pRootSignature = mSsaoRootSignature.Get();
  1378.     ssaoPsoDesc.VS =
  1379.     {
  1380.         reinterpret_cast<BYTE*>(mShaders["ssaoVS"]->GetBufferPointer()),
  1381.         mShaders["ssaoVS"]->GetBufferSize()
  1382.     };
  1383.     ssaoPsoDesc.PS =
  1384.     {
  1385.         reinterpret_cast<BYTE*>(mShaders["ssaoPS"]->GetBufferPointer()),
  1386.         mShaders["ssaoPS"]->GetBufferSize()
  1387.     };
  1388.  
  1389.     // SSAO effect does not need the depth buffer.
  1390.     ssaoPsoDesc.DepthStencilState.DepthEnable = false;
  1391.     ssaoPsoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
  1392.     ssaoPsoDesc.RTVFormats[0] = Ssao::AmbientMapFormat;
  1393.     ssaoPsoDesc.SampleDesc.Count = 1;
  1394.     ssaoPsoDesc.SampleDesc.Quality = 0;
  1395.     ssaoPsoDesc.DSVFormat = DXGI_FORMAT_UNKNOWN;
  1396.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&ssaoPsoDesc, IID_PPV_ARGS(&mPSOs["ssao"])));
  1397.  
  1398.     //
  1399.     // PSO for SSAO blur.
  1400.     //
  1401.     D3D12_GRAPHICS_PIPELINE_STATE_DESC ssaoBlurPsoDesc = ssaoPsoDesc;
  1402.     ssaoBlurPsoDesc.VS =
  1403.     {
  1404.         reinterpret_cast<BYTE*>(mShaders["ssaoBlurVS"]->GetBufferPointer()),
  1405.         mShaders["ssaoBlurVS"]->GetBufferSize()
  1406.     };
  1407.     ssaoBlurPsoDesc.PS =
  1408.     {
  1409.         reinterpret_cast<BYTE*>(mShaders["ssaoBlurPS"]->GetBufferPointer()),
  1410.         mShaders["ssaoBlurPS"]->GetBufferSize()
  1411.     };
  1412.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&ssaoBlurPsoDesc, IID_PPV_ARGS(&mPSOs["ssaoBlur"])));
  1413.  
  1414.     //
  1415.     // PSO for sky.
  1416.     //
  1417.     D3D12_GRAPHICS_PIPELINE_STATE_DESC skyPsoDesc = basePsoDesc;
  1418.  
  1419.     // The camera is inside the sky sphere, so just turn off culling.
  1420.     skyPsoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
  1421.  
  1422.     // Make sure the depth function is LESS_EQUAL and not just LESS.  
  1423.     // Otherwise, the normalized depth values at z = 1 (NDC) will 
  1424.     // fail the depth test if the depth buffer was cleared to 1.
  1425.     skyPsoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
  1426.     skyPsoDesc.pRootSignature = mRootSignature.Get();
  1427.     skyPsoDesc.VS =
  1428.     {
  1429.         reinterpret_cast<BYTE*>(mShaders["skyVS"]->GetBufferPointer()),
  1430.         mShaders["skyVS"]->GetBufferSize()
  1431.     };
  1432.     skyPsoDesc.PS =
  1433.     {
  1434.         reinterpret_cast<BYTE*>(mShaders["skyPS"]->GetBufferPointer()),
  1435.         mShaders["skyPS"]->GetBufferSize()
  1436.     };
  1437.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&skyPsoDesc, IID_PPV_ARGS(&mPSOs["sky"])));
  1438.  
  1439. }
  1440.  
  1441. void SsaoApp::BuildFrameResources()
  1442. {
  1443.     for(int i = 0; i < gNumFrameResources; ++i)
  1444.     {
  1445.         mFrameResources.push_back(std::make_unique<FrameResource>(md3dDevice.Get(),
  1446.             2, (UINT)mAllRitems.size(), (UINT)mMaterials.size()));
  1447.     }
  1448. }
  1449.  
  1450. void SsaoApp::BuildMaterials()
  1451. {
  1452.     auto bricks0 = std::make_unique<Material>();
  1453.     bricks0->Name = "bricks0";
  1454.     bricks0->MatCBIndex = 0;
  1455.     bricks0->DiffuseSrvHeapIndex = 0;
  1456.     bricks0->NormalSrvHeapIndex = 1;
  1457.     bricks0->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  1458.     bricks0->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
  1459.     bricks0->Roughness = 0.3f;
  1460.  
  1461.     auto tile0 = std::make_unique<Material>();
  1462.     tile0->Name = "tile0";
  1463.     tile0->MatCBIndex = 2;
  1464.     tile0->DiffuseSrvHeapIndex = 2;
  1465.     tile0->NormalSrvHeapIndex = 3;
  1466.     tile0->DiffuseAlbedo = XMFLOAT4(0.9f, 0.9f, 0.9f, 1.0f);
  1467.     tile0->FresnelR0 = XMFLOAT3(0.2f, 0.2f, 0.2f);
  1468.     tile0->Roughness = 0.1f;
  1469.  
  1470.     auto mirror0 = std::make_unique<Material>();
  1471.     mirror0->Name = "mirror0";
  1472.     mirror0->MatCBIndex = 3;
  1473.     mirror0->DiffuseSrvHeapIndex = 4;
  1474.     mirror0->NormalSrvHeapIndex = 5;
  1475.     mirror0->DiffuseAlbedo = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
  1476.     mirror0->FresnelR0 = XMFLOAT3(0.98f, 0.97f, 0.95f);
  1477.     mirror0->Roughness = 0.1f;
  1478.  
  1479.     auto skullMat = std::make_unique<Material>();
  1480.     skullMat->Name = "skullMat";
  1481.     skullMat->MatCBIndex = 3;
  1482.     skullMat->DiffuseSrvHeapIndex = 4;
  1483.     skullMat->NormalSrvHeapIndex = 5;
  1484.     skullMat->DiffuseAlbedo = XMFLOAT4(0.3f, 0.3f, 0.3f, 1.0f);
  1485.     skullMat->FresnelR0 = XMFLOAT3(0.6f, 0.6f, 0.6f);
  1486.     skullMat->Roughness = 0.2f;
  1487.  
  1488.     auto sky = std::make_unique<Material>();
  1489.     sky->Name = "sky";
  1490.     sky->MatCBIndex = 4;
  1491.     sky->DiffuseSrvHeapIndex = 6;
  1492.     sky->NormalSrvHeapIndex = 7;
  1493.     sky->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  1494.     sky->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
  1495.     sky->Roughness = 1.0f;
  1496.  
  1497.     mMaterials["bricks0"] = std::move(bricks0);
  1498.     mMaterials["tile0"] = std::move(tile0);
  1499.     mMaterials["mirror0"] = std::move(mirror0);
  1500.     mMaterials["skullMat"] = std::move(skullMat);
  1501.     mMaterials["sky"] = std::move(sky);
  1502. }
  1503.  
  1504. void SsaoApp::BuildRenderItems()
  1505. {
  1506.     auto skyRitem = std::make_unique<RenderItem>();
  1507.     XMStoreFloat4x4(&skyRitem->World, XMMatrixScaling(5000.0f, 5000.0f, 5000.0f));
  1508.     skyRitem->TexTransform = MathHelper::Identity4x4();
  1509.     skyRitem->ObjCBIndex = 0;
  1510.     skyRitem->Mat = mMaterials["sky"].get();
  1511.     skyRitem->Geo = mGeometries["shapeGeo"].get();
  1512.     skyRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1513.     skyRitem->IndexCount = skyRitem->Geo->DrawArgs["sphere"].IndexCount;
  1514.     skyRitem->StartIndexLocation = skyRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1515.     skyRitem->BaseVertexLocation = skyRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1516.  
  1517.     mRitemLayer[(int)RenderLayer::Sky].push_back(skyRitem.get());
  1518.     mAllRitems.push_back(std::move(skyRitem));
  1519.     
  1520.     auto quadRitem = std::make_unique<RenderItem>();
  1521.     quadRitem->World = MathHelper::Identity4x4();
  1522.     quadRitem->TexTransform = MathHelper::Identity4x4();
  1523.     quadRitem->ObjCBIndex = 1;
  1524.     quadRitem->Mat = mMaterials["bricks0"].get();
  1525.     quadRitem->Geo = mGeometries["shapeGeo"].get();
  1526.     quadRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1527.     quadRitem->IndexCount = quadRitem->Geo->DrawArgs["quad"].IndexCount;
  1528.     quadRitem->StartIndexLocation = quadRitem->Geo->DrawArgs["quad"].StartIndexLocation;
  1529.     quadRitem->BaseVertexLocation = quadRitem->Geo->DrawArgs["quad"].BaseVertexLocation;
  1530.  
  1531.     mRitemLayer[(int)RenderLayer::Debug].push_back(quadRitem.get());
  1532.     mAllRitems.push_back(std::move(quadRitem));
  1533.     
  1534.     auto boxRitem = std::make_unique<RenderItem>();
  1535.     XMStoreFloat4x4(&boxRitem->World, XMMatrixScaling(2.0f, 1.0f, 2.0f)*XMMatrixTranslation(0.0f, 0.5f, 0.0f));
  1536.     XMStoreFloat4x4(&boxRitem->TexTransform, XMMatrixScaling(1.0f, 0.5f, 1.0f));
  1537.     boxRitem->ObjCBIndex = 2;
  1538.     boxRitem->Mat = mMaterials["bricks0"].get();
  1539.     boxRitem->Geo = mGeometries["shapeGeo"].get();
  1540.     boxRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1541.     boxRitem->IndexCount = boxRitem->Geo->DrawArgs["box"].IndexCount;
  1542.     boxRitem->StartIndexLocation = boxRitem->Geo->DrawArgs["box"].StartIndexLocation;
  1543.     boxRitem->BaseVertexLocation = boxRitem->Geo->DrawArgs["box"].BaseVertexLocation;
  1544.  
  1545.     mRitemLayer[(int)RenderLayer::Opaque].push_back(boxRitem.get());
  1546.     mAllRitems.push_back(std::move(boxRitem));
  1547.  
  1548.     auto skullRitem = std::make_unique<RenderItem>();
  1549.     XMStoreFloat4x4(&skullRitem->World, XMMatrixScaling(0.4f, 0.4f, 0.4f)*XMMatrixTranslation(0.0f, 1.0f, 0.0f));
  1550.     skullRitem->TexTransform = MathHelper::Identity4x4();
  1551.     skullRitem->ObjCBIndex = 3;
  1552.     skullRitem->Mat = mMaterials["skullMat"].get();
  1553.     skullRitem->Geo = mGeometries["skullGeo"].get();
  1554.     skullRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1555.     skullRitem->IndexCount = skullRitem->Geo->DrawArgs["skull"].IndexCount;
  1556.     skullRitem->StartIndexLocation = skullRitem->Geo->DrawArgs["skull"].StartIndexLocation;
  1557.     skullRitem->BaseVertexLocation = skullRitem->Geo->DrawArgs["skull"].BaseVertexLocation;
  1558.  
  1559.     mRitemLayer[(int)RenderLayer::Opaque].push_back(skullRitem.get());
  1560.     mAllRitems.push_back(std::move(skullRitem));
  1561.  
  1562.     auto gridRitem = std::make_unique<RenderItem>();
  1563.     gridRitem->World = MathHelper::Identity4x4();
  1564.     XMStoreFloat4x4(&gridRitem->TexTransform, XMMatrixScaling(8.0f, 8.0f, 1.0f));
  1565.     gridRitem->ObjCBIndex = 4;
  1566.     gridRitem->Mat = mMaterials["tile0"].get();
  1567.     gridRitem->Geo = mGeometries["shapeGeo"].get();
  1568.     gridRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1569.     gridRitem->IndexCount = gridRitem->Geo->DrawArgs["grid"].IndexCount;
  1570.     gridRitem->StartIndexLocation = gridRitem->Geo->DrawArgs["grid"].StartIndexLocation;
  1571.     gridRitem->BaseVertexLocation = gridRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
  1572.  
  1573.     mRitemLayer[(int)RenderLayer::Opaque].push_back(gridRitem.get());
  1574.     mAllRitems.push_back(std::move(gridRitem));
  1575.  
  1576.     XMMATRIX brickTexTransform = XMMatrixScaling(1.5f, 2.0f, 1.0f);
  1577.     UINT objCBIndex = 5;
  1578.     for(int i = 0; i < 5; ++i)
  1579.     {
  1580.         auto leftCylRitem = std::make_unique<RenderItem>();
  1581.         auto rightCylRitem = std::make_unique<RenderItem>();
  1582.         auto leftSphereRitem = std::make_unique<RenderItem>();
  1583.         auto rightSphereRitem = std::make_unique<RenderItem>();
  1584.  
  1585.         XMMATRIX leftCylWorld = XMMatrixTranslation(-5.0f, 1.5f, -10.0f + i*5.0f);
  1586.         XMMATRIX rightCylWorld = XMMatrixTranslation(+5.0f, 1.5f, -10.0f + i*5.0f);
  1587.  
  1588.         XMMATRIX leftSphereWorld = XMMatrixTranslation(-5.0f, 3.5f, -10.0f + i*5.0f);
  1589.         XMMATRIX rightSphereWorld = XMMatrixTranslation(+5.0f, 3.5f, -10.0f + i*5.0f);
  1590.  
  1591.         XMStoreFloat4x4(&leftCylRitem->World, rightCylWorld);
  1592.         XMStoreFloat4x4(&leftCylRitem->TexTransform, brickTexTransform);
  1593.         leftCylRitem->ObjCBIndex = objCBIndex++;
  1594.         leftCylRitem->Mat = mMaterials["bricks0"].get();
  1595.         leftCylRitem->Geo = mGeometries["shapeGeo"].get();
  1596.         leftCylRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1597.         leftCylRitem->IndexCount = leftCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
  1598.         leftCylRitem->StartIndexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
  1599.         leftCylRitem->BaseVertexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
  1600.  
  1601.         XMStoreFloat4x4(&rightCylRitem->World, leftCylWorld);
  1602.         XMStoreFloat4x4(&rightCylRitem->TexTransform, brickTexTransform);
  1603.         rightCylRitem->ObjCBIndex = objCBIndex++;
  1604.         rightCylRitem->Mat = mMaterials["bricks0"].get();
  1605.         rightCylRitem->Geo = mGeometries["shapeGeo"].get();
  1606.         rightCylRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1607.         rightCylRitem->IndexCount = rightCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
  1608.         rightCylRitem->StartIndexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
  1609.         rightCylRitem->BaseVertexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
  1610.  
  1611.         XMStoreFloat4x4(&leftSphereRitem->World, leftSphereWorld);
  1612.         leftSphereRitem->TexTransform = MathHelper::Identity4x4();
  1613.         leftSphereRitem->ObjCBIndex = objCBIndex++;
  1614.         leftSphereRitem->Mat = mMaterials["mirror0"].get();
  1615.         leftSphereRitem->Geo = mGeometries["shapeGeo"].get();
  1616.         leftSphereRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1617.         leftSphereRitem->IndexCount = leftSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
  1618.         leftSphereRitem->StartIndexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1619.         leftSphereRitem->BaseVertexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1620.  
  1621.         XMStoreFloat4x4(&rightSphereRitem->World, rightSphereWorld);
  1622.         rightSphereRitem->TexTransform = MathHelper::Identity4x4();
  1623.         rightSphereRitem->ObjCBIndex = objCBIndex++;
  1624.         rightSphereRitem->Mat = mMaterials["mirror0"].get();
  1625.         rightSphereRitem->Geo = mGeometries["shapeGeo"].get();
  1626.         rightSphereRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1627.         rightSphereRitem->IndexCount = rightSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
  1628.         rightSphereRitem->StartIndexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1629.         rightSphereRitem->BaseVertexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1630.  
  1631.         mRitemLayer[(int)RenderLayer::Opaque].push_back(leftCylRitem.get());
  1632.         mRitemLayer[(int)RenderLayer::Opaque].push_back(rightCylRitem.get());
  1633.         mRitemLayer[(int)RenderLayer::Opaque].push_back(leftSphereRitem.get());
  1634.         mRitemLayer[(int)RenderLayer::Opaque].push_back(rightSphereRitem.get());
  1635.  
  1636.         mAllRitems.push_back(std::move(leftCylRitem));
  1637.         mAllRitems.push_back(std::move(rightCylRitem));
  1638.         mAllRitems.push_back(std::move(leftSphereRitem));
  1639.         mAllRitems.push_back(std::move(rightSphereRitem));
  1640.     }
  1641. }
  1642.  
  1643. void SsaoApp::DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems)
  1644. {
  1645.     UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));
  1646.  
  1647.     auto objectCB = mCurrFrameResource->ObjectCB->Resource();
  1648.  
  1649.     // For each render item...
  1650.     for(size_t i = 0; i < ritems.size(); ++i)
  1651.     {
  1652.         auto ri = ritems[i];
  1653.  
  1654.         cmdList->IASetVertexBuffers(0, 1, &ri->Geo->VertexBufferView());
  1655.         cmdList->IASetIndexBuffer(&ri->Geo->IndexBufferView());
  1656.         cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
  1657.  
  1658.         D3D12_GPU_VIRTUAL_ADDRESS objCBAddress = objectCB->GetGPUVirtualAddress() + ri->ObjCBIndex*objCBByteSize;
  1659.  
  1660.         cmdList->SetGraphicsRootConstantBufferView(0, objCBAddress);
  1661.  
  1662.         cmdList->DrawIndexedInstanced(ri->IndexCount, 1, ri->StartIndexLocation, ri->BaseVertexLocation, 0);
  1663.     }
  1664. }
  1665.  
  1666. void SsaoApp::DrawSceneToShadowMap()
  1667. {
  1668.     mCommandList->RSSetViewports(1, &mShadowMap->Viewport());
  1669.     mCommandList->RSSetScissorRects(1, &mShadowMap->ScissorRect());
  1670.  
  1671.     // Change to DEPTH_WRITE.
  1672.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mShadowMap->Resource(),
  1673.         D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE));
  1674.  
  1675.     // Clear the back buffer and depth buffer.
  1676.     mCommandList->ClearDepthStencilView(mShadowMap->Dsv(), 
  1677.         D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  1678.  
  1679.     // Specify the buffers we are going to render to.
  1680.     mCommandList->OMSetRenderTargets(0, nullptr, false, &mShadowMap->Dsv());
  1681.  
  1682.     // Bind the pass constant buffer for the shadow map pass.
  1683.     UINT passCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(PassConstants));
  1684.     auto passCB = mCurrFrameResource->PassCB->Resource();
  1685.     D3D12_GPU_VIRTUAL_ADDRESS passCBAddress = passCB->GetGPUVirtualAddress() + 1*passCBByteSize;
  1686.     mCommandList->SetGraphicsRootConstantBufferView(1, passCBAddress);
  1687.  
  1688.     mCommandList->SetPipelineState(mPSOs["shadow_opaque"].Get());
  1689.  
  1690.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
  1691.  
  1692.     // Change back to GENERIC_READ so we can read the texture in a shader.
  1693.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mShadowMap->Resource(),
  1694.         D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ));
  1695. }
  1696.  
  1697. void SsaoApp::DrawNormalsAndDepth()
  1698. {
  1699.     mCommandList->RSSetViewports(1, &mScreenViewport);
  1700.     mCommandList->RSSetScissorRects(1, &mScissorRect);
  1701.  
  1702.     auto normalMap = mSsao->NormalMap();
  1703.     auto normalMapRtv = mSsao->NormalMapRtv();
  1704.     
  1705.     // Change to RENDER_TARGET.
  1706.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(normalMap,
  1707.         D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET));
  1708.  
  1709.     // Clear the screen normal map and depth buffer.
  1710.     float clearValue[] = {0.0f, 0.0f, 1.0f, 0.0f};
  1711.     mCommandList->ClearRenderTargetView(normalMapRtv, clearValue, 0, nullptr);
  1712.     mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  1713.  
  1714.     // Specify the buffers we are going to render to.
  1715.     mCommandList->OMSetRenderTargets(1, &normalMapRtv, true, &DepthStencilView());
  1716.  
  1717.     // Bind the constant buffer for this pass.
  1718.     auto passCB = mCurrFrameResource->PassCB->Resource();
  1719.     mCommandList->SetGraphicsRootConstantBufferView(1, passCB->GetGPUVirtualAddress());
  1720.  
  1721.     mCommandList->SetPipelineState(mPSOs["drawNormals"].Get());
  1722.  
  1723.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
  1724.  
  1725.     // Change back to GENERIC_READ so we can read the texture in a shader.
  1726.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(normalMap,
  1727.         D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
  1728. }
  1729.  
  1730. CD3DX12_CPU_DESCRIPTOR_HANDLE SsaoApp::GetCpuSrv(int index)const
  1731. {
  1732.     auto srv = CD3DX12_CPU_DESCRIPTOR_HANDLE(mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
  1733.     srv.Offset(index, mCbvSrvUavDescriptorSize);
  1734.     return srv;
  1735. }
  1736.  
  1737. CD3DX12_GPU_DESCRIPTOR_HANDLE SsaoApp::GetGpuSrv(int index)const
  1738. {
  1739.     auto srv = CD3DX12_GPU_DESCRIPTOR_HANDLE(mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  1740.     srv.Offset(index, mCbvSrvUavDescriptorSize);
  1741.     return srv;
  1742. }
  1743.  
  1744. CD3DX12_CPU_DESCRIPTOR_HANDLE SsaoApp::GetDsv(int index)const
  1745. {
  1746.     auto dsv = CD3DX12_CPU_DESCRIPTOR_HANDLE(mDsvHeap->GetCPUDescriptorHandleForHeapStart());
  1747.     dsv.Offset(index, mDsvDescriptorSize);
  1748.     return dsv;
  1749. }
  1750.  
  1751. CD3DX12_CPU_DESCRIPTOR_HANDLE SsaoApp::GetRtv(int index)const
  1752. {
  1753.     auto rtv = CD3DX12_CPU_DESCRIPTOR_HANDLE(mRtvHeap->GetCPUDescriptorHandleForHeapStart());
  1754.     rtv.Offset(index, mRtvDescriptorSize);
  1755.     return rtv;
  1756. }
  1757.  
  1758. std::array<const CD3DX12_STATIC_SAMPLER_DESC, 7> SsaoApp::GetStaticSamplers()
  1759. {
  1760.     // Applications usually only need a handful of samplers.  So just define them all up front
  1761.     // and keep them available as part of the root signature.  
  1762.  
  1763.     const CD3DX12_STATIC_SAMPLER_DESC pointWrap(
  1764.         0, // shaderRegister
  1765.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  1766.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1767.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1768.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  1769.  
  1770.     const CD3DX12_STATIC_SAMPLER_DESC pointClamp(
  1771.         1, // shaderRegister
  1772.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  1773.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1774.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1775.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  1776.  
  1777.     const CD3DX12_STATIC_SAMPLER_DESC linearWrap(
  1778.         2, // shaderRegister
  1779.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  1780.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1781.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1782.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  1783.  
  1784.     const CD3DX12_STATIC_SAMPLER_DESC linearClamp(
  1785.         3, // shaderRegister
  1786.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  1787.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1788.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1789.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  1790.  
  1791.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicWrap(
  1792.         4, // shaderRegister
  1793.         D3D12_FILTER_ANISOTROPIC, // filter
  1794.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1795.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1796.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressW
  1797.         0.0f,                             // mipLODBias
  1798.         8);                               // maxAnisotropy
  1799.  
  1800.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicClamp(
  1801.         5, // shaderRegister
  1802.         D3D12_FILTER_ANISOTROPIC, // filter
  1803.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1804.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1805.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressW
  1806.         0.0f,                              // mipLODBias
  1807.         8);                                // maxAnisotropy
  1808.  
  1809.     const CD3DX12_STATIC_SAMPLER_DESC shadow(
  1810.         6, // shaderRegister
  1811.         D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT, // filter
  1812.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressU
  1813.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressV
  1814.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressW
  1815.         0.0f,                               // mipLODBias
  1816.         16,                                 // maxAnisotropy
  1817.         D3D12_COMPARISON_FUNC_LESS_EQUAL,
  1818.         D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK);
  1819.  
  1820.     return { 
  1821.         pointWrap, pointClamp,
  1822.         linearWrap, linearClamp, 
  1823.         anisotropicWrap, anisotropicClamp,
  1824.         shadow 
  1825.     };
  1826. }
  1827.  
  1828.